#include "stdio.h"
#include "sys/socket.h"
#include "sys/types.h"
#include "unistd.h"
#include "errno.h"
#include "string.h"
#include "stdlib.h"
#include "netinet/in.h"
#include "arpa/inet.h"
#include "netdb.h"
#include "sys/fcntl.h"

int fd = NULL;
int filefd = NULL;
const mode_t MOD_644 = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;

void quit() {
    if (fd) {
        printf("closing %d \n", fd);
        close(fd);
    }
    if (filefd) {
        printf("closing file fd %d \n", filefd);
        close(filefd);
    }
    exit(1);
}

int main(int argc, char *argv[]) {
    fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    printf("fd = %d \n", fd);
    if (fd == -1) {
        printf("error is : %d %s \n", errno, strerror(errno));
        quit();
    }

//    struct sockaddr_in addrin = {};
//    addrin.sin_family = AF_INET;
//    addrin.sin_port = htons(8201);
//    printf("port is = %d \n", addrin.sin_port);
//    addrin.sin_addr.s_addr = inet_addr("192.168.31.220");
//    printf("addr int = %d \n", addrin.sin_addr.s_addr);
//    if (addrin.sin_addr.s_addr == -1) {
//        printf("error is : %d %s \n", errno, strerror(errno));
//        exit(1);
//    }

//    int res = connect(fd, (struct sockaddr *)&addrin, sizeof(struct sockaddr));
//    printf("connect res = %d \n", res);
//    if (res != 0) {
//        printf("error is : %d %s \n", errno, strerror(errno));
//        exit(1);
//    }
//
//    char *empty_request = "";
//
//    ssize_t send_res = send(fd, empty_request, 1, MSG_OOB);
//    printf("send res = %d \n", send_res);
//    if (send_res != 1) {
//        printf("send error is : %d %s \n", errno, strerror(errno));
//        exit(1);
//    }
//
//    char buffer[1024];
//
//    ssize_t read_length = recv(fd, buffer, 1024, MSG_WAITALL);
//    printf("read length 1 %d \n", read_length);
//    while (read_length) {
//        if (read_length == -1) {
//            printf("send error is : %d %s \n", errno, strerror(errno));
//        } else {
//            printf("read result: %s \n", buffer);
//        }
//        read_length = recv(fd, buffer, 1024, MSG_WAITALL);
//        printf("read length 2 %d \n", read_length);
//    }
//

    //https://img1.sdnlab.com/wp-cntent/uploads/12/wfw.jpg
    // http://tech.meijiabang.cn/wp-content/uploads/2018/05/xiaofeiji-409x160.jpg
    char *host = "tech.meijiabang.cn";
    printf("%u \n", strlen(host));
    struct hostent *res = gethostbyname(host);
    if (!res) {
        printf("fail getting ip... \n");
        quit();
    }

    printf("here ... %s \n", (*res).h_name);

    char **ptr = res->h_aliases;
    while (*ptr) {
        printf("alias: %s \n", *ptr);
        ptr++;
    }

    char *ip_res = NULL;
    for (int i = 0; res->h_addr_list[i]; i++) {
        ip_res = inet_ntoa(*(struct in_addr *) res->h_addr_list[i]);
        printf("addr2: %s \n", ip_res);
        break;
    }

    if (!ip_res) {
        printf("fail get ip... \n");
        quit();
    }

    printf("connecting... \n");
    struct sockaddr_in addrin = {0};
    addrin.sin_family = AF_INET;
    addrin.sin_port = htons(80);
    addrin.sin_addr.s_addr = inet_addr(ip_res);

    size_t connect_res = (size_t) connect(fd, (struct sockaddr *) &addrin, sizeof(struct sockaddr));
    if (connect_res != 0) {
        printf("connect failed \n");
        printf("error is : %d %s \n", errno, strerror(errno));
        quit();
    }

    printf("sending... \n");

    filefd = open("/data/src/2.jpg", O_WRONLY | O_CREAT | O_TRUNC, MOD_644);
    if (!filefd) {
        printf("fail opening file \n");
        quit();
    }

    char http_req[1024];
    memset(http_req, 0, 1024);
    char *format = "GET http://tech.meijiabang.cn/wp-content/uploads/2018/05/xiaofeiji-409x160.jpg HTTP/1.1\r\n"\
                            "Host:%s\r\n"\
                            "Connection:Close\r\n"\
                            "\r\n";
    sprintf(http_req, format, "tech.meijiabang.cn");
    printf("sizeof httprequest is : %d \n", (size_t) sizeof(http_req));

    size_t send_res = write(fd, http_req, sizeof(http_req));
    if (!send_res) {
        printf("fail sending... \n");
        quit();
    }

    printf("receiving... \n");
    char buffer[1024];
    size_t read_length = recv(fd, buffer, 1024, MSG_WAITALL);
    int found = 0;

    while (read_length) {
        printf("read length %d and res is : %s \n", read_length, buffer);

        if (!found) {
            for (int i = 0; i < read_length; i++) {
                if (strncmp(buffer + i, "\r\n\r\n", 4) == 0) {
                    printf("index: %d \n", i);
                    found = 1;
                    int skip_length = i + 4;
                    write(filefd, buffer + skip_length, read_length - skip_length);
                    break;
                }
            }
        } else {
            write(filefd, buffer, read_length);
        }
        read_length = recv(fd, buffer, 1024, MSG_WAITALL);
    }

    quit();
    return 0;

}
